import os
import re
from common import get_logger, browser, safe_filename, session
import subprocess

# 从config模块导入抖音视频保存的目录常量
from config import DOUYIN_SAVE_DIR

logger = get_logger(__name__)


def is_logged_in_js(tab):
    js_source = """
        if(document.querySelector("span.semi-avatar img")){
            return true;
        }
        return false;
    """
    try:
        return tab.run_js(js_source)
    except Exception as e:
        logger.error(f"检查登录时出现错误:{e}")
        tab.wait(2)  # time.sleep(2)


# 定义爬取抖音热门视频的函数，参数为关键词
def crawl_douyin_videos(keyword):
    logger.info("开始爬取抖音热门视频")

    # 构建抖音搜索的页面的URL地址
    url = f"https://www.douyin.com/root/search/{keyword}?type=video"
    # 如果保存视频的目录不存在，则创建该目录
    if not os.path.exists(DOUYIN_SAVE_DIR):
        os.makedirs(DOUYIN_SAVE_DIR)
    # 打开新的标签页，并且访问抖音搜索地址
    tab = browser.new_tab(url)
    # 启动监听，捕获视频的真实地址
    tab.listen.start("/video/tos")
    while True:
        try:
            if is_logged_in_js(tab):
                break
            logger.info(f"等待登录中，请扫码登录抖音账号")
            tab.wait(2)
        except Exception as e:
            logger.error(f"等待登录异常:{e}")
            tab.wait(2)  # time.sleep(2)
    logger.info(f"检测到已经登录，继续执行")
    # 获取所有的视频卡片元素
    video_cards = tab.eles(".search-result-card")
    logger.info(f"共找到{len(video_cards)}个视频卡片")
    # 只处理第一个卡片
    video_cards = video_cards[:1]
    logger.info(f"先处理{len(video_cards)}个视频卡片")

    # 初始化视频文件的列表
    video_files = []
    # 遍历每个卡片 idx为序号 card为卡片的元素
    for idx, card in enumerate(video_cards, 1):
        try:
            # 鼠标悬停到卡片
            card.hover()
            # 获取视频标题
            title = card.ele(".VDYK8Xd7").text
            # 生成安全的文件名
            filename = safe_filename(idx, title, ".mp4")
            logger.info(f"视频文件名:{filename}")
            # 等待监听获取真实的视频地址
            # real_video_url = tab.listen.wait().url
            real_video_url = "https://v26-web.douyinvod.com/4fecb1ea2d9eb82c99f6bc296a00e611/685fc008/video/tos/cn/tos-cn-ve-15c000-ce/okCiATcKmihhCAIQI0iBwJfIEvRbwG81EeZDNe/?a=6383&ch=11&cr=3&dr=0&lr=all&cd=0%7C0%7C0%7C3&cv=1&br=1689&bt=1689&cs=0&ds=4&ft=AJkeU_TLRR0sWrC12D12Nc.xBiGNbLdAeIdU_4l-ria2Nv7TGW&mime_type=video_mp4&qs=0&rc=OjVkNzo6Zzk6NmhmZmc0ZEBpM3ZqZ2o5cjRqNDMzbGkzNEAxYjM2Yy81NTUxNV9fYTJgYSMxbmMuMmRzMzVhLS1kLWJzcw%3D%3D&btag=80000e00028000&cquery=101n_100B_100x_100z_100o&dy_q=1751094581&feature_id=0ea98fd3bdc3c6c14a3d0804cc272721&l=20250628150941AF2C9762B4BE6B860A01"
            logger.info(f"真实的视频为:{idx} {real_video_url}")
            # 发送GET请求视频地址获取视频数据
            video_data = session.get(
                real_video_url,
                headers={
                    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
                    "referer": "https://www.douyin.com/",
                    "cookie": "SEARCH_RESULT_LIST_TYPE=%22single%22; hevc_supported=true; fpk1=U2FsdGVkX1+sLMfsRf8uK31dfGpeKSwnKlTb727ByZKNYYz3jy9m0APHrKe63PaNHSNGmS5WFNgrlNHcUiaTpg==; fpk2=0fe6feb54289f4c67027ec06cc2131f8; passport_csrf_token=793a770416ba0e71479b383fed15a152; passport_csrf_token_default=793a770416ba0e71479b383fed15a152; __security_mc_1_s_sdk_crypt_sdk=a3a9d23f-4bc2-bd60; bd_ticket_guard_client_web_domain=2; passport_mfa_token=CjWtqDvy5oa8nOmJiSr%2FwuiOkt%2F2RfGbhRcPLAKqstNu5nzL8eW2C3R%2Bf9qGjikN7p3z9Bv%2BpxpKCjwAAAAAAAAAAAAATyoxxtJWSTn7wXwuIPDJHt7CqNvbrzCG13QUNvmQPCC5kph3%2BTbc%2BFKJ3%2BiEQLG7c38QnKP1DRj2sdFsIAIiAQN%2BRKAu; d_ticket=56d6353979284da627e7bee61fed4bd247c81; passport_assist_user=CjwcZ7gzkrFMGoQ42N_EIy8Dc_h9TB5gkP71ffv7RFRwM6Xmc89jQwIIVOI53vXWtEYogC5cnAlxm7n7JqMaSgo8AAAAAAAAAAAAAE8qByjtv9TOl-wSI2FXsoA9RsCNLasyESZ3wttwLCF69XHqbMER4eSlTVUCk2EJzDc8EI-i9Q0Yia_WVCABIgED7zVT3Q%3D%3D; n_mh=ePaPjIgO1xajYk5aindDk9jHfeDEBVUianOwPU0v9X0; sid_guard=796747f0f70d5f5e319a2bc59e1a92db%7C1751075298%7C5184000%7CWed%2C+27-Aug-2025+01%3A48%3A18+GMT; uid_tt=aaadceb9e91c89ac05a4111d8bb927ad; uid_tt_ss=aaadceb9e91c89ac05a4111d8bb927ad; sid_tt=796747f0f70d5f5e319a2bc59e1a92db; sessionid=796747f0f70d5f5e319a2bc59e1a92db; sessionid_ss=796747f0f70d5f5e319a2bc59e1a92db; session_tlb_tag=sttt%7C12%7CeWdH8PcNX14xmivFnhqS2__________OECNKrPn_p_MfYaplP61oVSzueEmTkLkX1tmnTopgswY%3D; is_staff_user=false; sid_ucp_v1=1.0.0-KDFkZTgzMWFjNDdiMzNlMzJlYmY3MGEwNzg1OWMyNjI5ODI5M2U1NDgKHwjz44yr5QIQ4pP9wgYY7zEgDDCLw9TVBTgHQPQHSAQaAmxmIiA3OTY3NDdmMGY3MGQ1ZjVlMzE5YTJiYzU5ZTFhOTJkYg; ssid_ucp_v1=1.0.0-KDFkZTgzMWFjNDdiMzNlMzJlYmY3MGEwNzg1OWMyNjI5ODI5M2U1NDgKHwjz44yr5QIQ4pP9wgYY7zEgDDCLw9TVBTgHQPQHSAQaAmxmIiA3OTY3NDdmMGY3MGQ1ZjVlMzE5YTJiYzU5ZTFhOTJkYg; login_time=1751075298211; SelfTabRedDotControl=%5B%5D; _bd_ticket_crypt_cookie=d7f2b0dff7089a107ea7eb2d314b2f4d; __security_mc_1_s_sdk_sign_data_key_web_protect=edc08d54-4543-9e3f; __security_mc_1_s_sdk_cert_key=6fa8ad0f-4a85-9ce9; __security_server_data_status=1; publish_badge_show_info=%220%2C0%2C0%2C1751075307070%22; enter_pc_once=1; UIFID=e71d819f1cb72e7166823ce125547a3e5a83b631a52f7c0b3c34cd9714dd602d38f793d894b342702e2809d1cc8ea24362f8ed1a62fe35530d8a9aef35fa53c2204cdf405a34b166e1c9121934ea7ec2945f0d7755cabf888d0347a7e5b6bbfcb946dc93cd445fc78ab6bcdc3193ace386d36b4312d65a0945d3f77a9aa08ecdad8fd270ec43e9956987289da28d3f247d2610eddd85459009857dec34f2a705; s_v_web_id=verify_mcflc370_3wF4HjTT_xUSK_4a40_8xE7_mxXZxo0Gs6Zt; dy_swidth=1920; dy_sheight=1080; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1920%2C%5C%22screen_height%5C%22%3A1080%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A12%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A100%7D%22; my_rd=2; ttwid=1%7CDgOCJtxtG5LTM01VcGZxZn0QW7hYedcZeX2PK3zQLY8%7C1751075828%7Cbc493e1e01d2d105da279fe190202ff31dd3dd29a3299c7adb20ca71655e63ef; csrf_session_id=b4ac659fff1f9481dc75b78ac7216add; __ac_nonce=0685f639600b843dcd4de; __ac_signature=_02B4Z6wo00f01XrirrQAAIDBTcZq6AxTvs16wqoAADbr73; download_guide=%223%2F20250628%2F1%22; WallpaperGuide=%7B%22showTime%22%3A1751075425881%2C%22closeTime%22%3A0%2C%22showCount%22%3A1%2C%22cursor1%22%3A58%2C%22cursor2%22%3A6%7D; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAGZqOg6E1nB2NcPTqRA6ZLgvQFzixd8YIu133wLj80hA%2F1751126400000%2F0%2F1751083128758%2F0%22; passport_fe_beating_status=true; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCSDh4TGVyRFhkSjJBZlFhU0VMZjk5cjkzaS90N1F4RGxPdi9qYUxPYlBIaUg3RzJ4eEFrcGhzRDNTUVB6R1lIYzROaDFvOWFQbW9EMUhLMlNmMCt1bkk9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoyfQ%3D%3D; home_can_add_dy_2_desktop=%221%22; odin_tt=72fcf5f92cb4c8911bdec01ede6f8668304b5816c13f986d2eb4ba2020114e92ffd226f3eaca0d0d3aa231f684857214e3958e67c9f25eeec35e02dc6f5e682f; IsDouyinActive=true",
                },
                timeout=10,
            )
            # 拼接保存的文件的路径
            file_path = os.path.join(
                os.path.dirname(os.path.abspath(__file__)), DOUYIN_SAVE_DIR, filename
            )
            logger.info(f"保存的路径为:{file_path}")
            # 以二进制的格式保存视频文件
            with open(file_path, "wb") as file:
                file.write(video_data.content)
                video_files.append(file_path)
        except Exception as e:
            logger.error(f"处理视频失败:{e}")
            continue
        finally:
            tab.wait(2)
    return video_files


def extract_audio(video_path):
    # 1.获得转换后的mp3的文件名
    base_name = os.path.basename(video_path)
    filename = os.path.splitext(base_name)[0]
    base_dir = os.path.dirname(video_path)
    mp3_path = os.path.join(base_dir, f"{filename}.mp3")
    # 构建命令行参数列表
    cmd = [
        "ffmpeg",
        "-y",  # 覆盖输出文件
        "-i",  # 输入文件
        video_path,
        "-vn",  # 不处理视频流
        "-acodec",  # 指定音频编码器
        "libmp3lame",
        "-ar",  # 指定音频采样率
        "44100",
        "-ac",  # 指定音频声道数
        "2",
        "-ab",  # 指定音频比特率
        "192k",
        mp3_path,  # 输出文件路径
    ]
    try:
        subprocess.run(cmd, check=True)
    except Exception as e:
        logger.error(f"音频提取失败:{e}")
    finally:
        return mp3_path
